package com.zf.yichat.service.impl;

import com.github.pagehelper.PageHelper;
import com.zf.yichat.dto.UserWidthdrawDto;
import com.zf.yichat.mapper.UserBankMapper;
import com.zf.yichat.mapper.UserBankXsMapper;
import com.zf.yichat.mapper.UserWithdrawMapper;
import com.zf.yichat.model.*;
import com.zf.yichat.service.BalanceService;
import com.zf.yichat.service.SysDictService;
import com.zf.yichat.service.UserService;
import com.zf.yichat.service.UserWithdrawService;
import com.zf.yichat.service.config.RedisService;
import com.zf.yichat.service.dto.UserWithdrawDto;
import com.zf.yichat.service.dto.WithdrawConfigDto;
import com.zf.yichat.utils.YiChatMsgCode;
import com.zf.yichat.utils.common.DateUtils;
import com.zf.yichat.utils.common.DtoChangeUtils;
import com.zf.yichat.utils.common.NumberUtils;
import com.zf.yichat.utils.response.FsPage;
import com.zf.yichat.utils.response.FsResponse;
import com.zf.yichat.utils.response.FsResponseGen;
import com.zf.yichat.vo.BalanceType;
import com.zf.yichat.vo.DictKey;
import org.apache.http.util.TextUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 一句话描述功能
 *
 * @author fengsong
 * @date create in 15:56 2019/7/25 2019
 */
@Service
public class UserWithdrawServiceImpl implements UserWithdrawService {
    private static Logger logger = LoggerFactory.getLogger(UserWithdrawServiceImpl.class);

    @Autowired
    private UserService userService;

    @Autowired
    private UserBankMapper userBankMapper;

    @Autowired
    private UserBankXsMapper userBankXsMapper;

    @Autowired
    private SysDictService sysDictService;

    @Autowired
    private BalanceService balanceService;

    @Autowired
    private UserWithdrawMapper userWithdrawMapper;

    //获取提现配置
    private WithdrawConfigDto getUserWithdrawConfig() {
        WithdrawConfigDto dto = new WithdrawConfigDto();

        dto.setMinLimit(Optional.ofNullable(sysDictService.selectOne(DictKey.sys_withdraw_money)).map(SysDict::getMemo).orElse("0"));
        dto.setRate(Optional.ofNullable(sysDictService.selectOne(DictKey.sys_withdraw_rate)).map(SysDict::getValue).orElse("0"));
        dto.setText(Optional.ofNullable(sysDictService.selectOne(DictKey.sys_withdraw_text)).map(SysDict::getMemo).orElse(""));
        dto.setAdd(Optional.ofNullable(sysDictService.selectOne(DictKey.sys_withdraw_add)).map(SysDict::getMemo).orElse("0"));
        dto.setCount(Optional.ofNullable(sysDictService.selectOne(DictKey.sys_withdraw_count)).map(SysDict::getMemo).orElse("3"));
        return dto;
    }

    @Override
    public void autoChekWithdaw() {
        SysDict auto = sysDictService.selectOne(DictKey.sys_withdraw_auto);
        logger.debug("提现审核检查");

        if (Objects.nonNull(auto)) {
            //自动通过
            String limitMoney = Optional.ofNullable(sysDictService.selectOne(DictKey.sys_withdraw_auto_money)).map(SysDict::getValue).orElse("0");
            String maxSecondStr = Optional.ofNullable(sysDictService.selectOne(DictKey.sys_withdraw_auto_time)).map(SysDict::getValue).orElse("120");

            logger.debug("自动提现金额：{}、时长：{}", limitMoney, maxSecondStr);
            int maxSecond;
            try {
                maxSecond = Integer.parseInt(maxSecondStr);
            } catch (Exception e) {
                maxSecond = 120;
            }
            Example example = new Example(UserWithdraw.class);
            example.createCriteria().andEqualTo("status", 0).andLessThanOrEqualTo("money", limitMoney);
            example.setOrderByClause("  id asc");
            List<UserWithdraw> withdraws = userWithdrawMapper.selectByExample(example);

            logger.debug("此次自动提现数：{}", limitMoney, maxSecondStr);
            Random random = new Random();
            for (UserWithdraw withdraw : withdraws) {
                int second = random.nextInt(maxSecond);
                try {
                    TimeUnit.SECONDS.sleep(second);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Example example2 = new Example(UserWithdraw.class);
                example2.createCriteria().andEqualTo("status", 1).andEqualTo("userId", withdraw.getUserId());
                int count = userWithdrawMapper.selectCountByExample(example2);
                if (count > 0) {
                    logger.debug("自动提现：{}", withdraw.getId());
                    balanceService.checkWithdraw(withdraw.getId(), 1, null);
                }
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FsResponse apply(Integer bankId, String memo, BigDecimal money, Long userId) {
        UserBank bank = userBankMapper.selectByPrimaryKey(bankId);
        if (Objects.isNull(bank)) {
            return FsResponseGen.failMsg("银行卡不存在");
        }
        if (!userId.equals(bank.getUserId())) {
            return FsResponseGen.failMsg("银行卡错误");
        }

        String minMoney=Optional.ofNullable(sysDictService.selectOne(DictKey.sys_withdraw_money)).map(SysDict::getMemo).orElse("100");
        String maxMoney=Optional.ofNullable(sysDictService.selectOne(DictKey.sys_withdraw_money_max)).map(SysDict::getMemo).orElse("3000");

        if (money.compareTo(new BigDecimal(minMoney)) < 0) {
            return FsResponseGen.failMsg("单笔最低提现"+minMoney+"元");
        }
        if (money.compareTo(new BigDecimal(maxMoney)) > 0) {
            return FsResponseGen.failMsg("单笔最高提现"+maxMoney+"元");
        }

        BigDecimal income = balanceService.selectByUserId(userId).getIncomeBalance();

        //余额不足
        if (income.compareTo(money) < 0) {
            return FsResponseGen.successData(YiChatMsgCode.WITHDRAW_APPLY_BALANCE_LITTLE, null);
        }
        WithdrawConfigDto config = getUserWithdrawConfig();
       // 今日提现次数
        Example example = new Example(UserWithdraw.class);
        Date date = new Date();
        example.createCriteria().andEqualTo("userId", userId).andBetween("ctime", DateUtils.formatDate(date, "yyyy-MM-dd 00:00:00"), DateUtils.formatDate(date, "yyyy-MM-dd 23:59:59"));
        int count = userWithdrawMapper.selectCountByExample(example);

        String setCount=config.getCount();
        int setCountInt=3;
        try {
            setCountInt=Integer.parseInt(setCount);
        }catch (Exception e){
            e.printStackTrace();
        }
        if (count > setCountInt-1) {
            return FsResponseGen.failMsg("单日最多提现"+setCount+"次");
        }

//        String xsBalance = redisService.getVal("xs_balance");
//        String hjBalance = redisService.getVal("hj_balance");
//        if (xsBalance != null && hjBalance != null) {
//            BigDecimal xsBalanceBig = new BigDecimal(xsBalance);
//            BigDecimal hjBalanceBig = new BigDecimal(hjBalance);
//            if (hjBalanceBig.compareTo(money) < 0 && xsBalanceBig.compareTo(money) > 0) {
//                return FsResponseGen.failMsg("该渠道今日已受限，请切换至渠道二提现");
//            } else {
//                redisService.setVal("hj_balance", hjBalanceBig.subtract(money).toString());
//            }
//        }


        //计算手续费
        BigDecimal rateF = new BigDecimal(config.getRate());
        rateF = money.multiply(rateF);
        rateF = rateF.divide(new BigDecimal("100"));
        rateF=rateF.add(new BigDecimal(config.getAdd()));
       // rateF = rateF.add(new BigDecimal("1"));
        rateF = rateF.setScale(2, BigDecimal.ROUND_HALF_UP);

        //计算实际到账
        BigDecimal realMoney = money.subtract(rateF).setScale(2, BigDecimal.ROUND_HALF_UP);

        //因为最低提现5元，所以实际到账不会低于0元
        User userMe= userService.selectById(bank.getUserId());


        //生成提现申请
        UserWithdraw withdraw = new UserWithdraw();
        withdraw.setBankName(bank.getBankName());
        withdraw.setBankNumber(bank.getBankNumber());
        withdraw.setMemo(memo);
        withdraw.setFutureMoney(realMoney);
        withdraw.setMoney(money);
        withdraw.setDetail("本次提现 " + money + " 元，手续费：" + rateF + " 元，实际到账：" + realMoney + "元");
        withdraw.setType(0);
        withdraw.setUserId(userId);
        withdraw.setCtime(new Date());
        withdraw.setParentCode(userMe.getRecommendCode());
        withdraw.setStatus(0);

        if(!TextUtils.isEmpty(userMe.getRecommendCode())){
            User parentUser=userService.selectByCode(userMe.getRecommendCode());
            //增加邀请人信息：
            if(parentUser!=null){
                withdraw.setParentUserId(String.valueOf(parentUser.getId()));
                withdraw.setParentPhone(parentUser.getMobile());
                withdraw.setParentUserNick(parentUser.getNick());

            }
        }


        //增加银行卡信息：
        withdraw.setCardBank(bank.getBankName());
        withdraw.setCardName(bank.getName());
        withdraw.setCardNo(bank.getBankNumber());
        withdraw.setCardBankChild(bank.getChildBankname());
        withdraw.setUserNick(userMe.getNick());


        userWithdrawMapper.insertUseGeneratedKeys(withdraw);

        //扣除余额到冻结
        balanceService.update(userId, BalanceType.WITHDRAW_APPLY, money, Long.valueOf(withdraw.getId()), "提现申请");

//        SysDict auto = sysDictService.selectOne(DictKey.sys_withdraw_auto);
//        if (Objects.nonNull(auto)) {
//        //自动通过
//        String limitMoney = Optional.ofNullable(sysDictService.selectOne(DictKey.sys_withdraw_auto_money)).map(SysDict::getValue).orElse("0");
//        if (money.compareTo(new BigDecimal(limitMoney)) > 0) {
//
//        } else {
//                balanceService.checkWithdraw(withdraw.getId(), 1, null);
//        }
//        }
//        Example example1 = new Example(UserBank.class);
//        example1.createCriteria().andEqualTo("bankNumber", cardNumber);
//        List<UserBank> banks = userBankMapper.selectByExample(example1);
//        if (Objects.nonNull(banks) && banks.size() > 0) {
//            bankName = banks.get(0).getBankName();
//        }

        return FsResponseGen.successData(DtoChangeUtils.getDto(NumberUtils.halfTwo(income.subtract(money)), v -> {
            UserWidthdrawDto dto = new UserWidthdrawDto();
            dto.setBalance(v);
            return dto;
        }));
    }

    @Autowired
    RedisService redisService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FsResponse apply2(Integer bankId, String memo, BigDecimal money, Long userId) {
        UserBankXs bank = userBankXsMapper.selectByPrimaryKey(bankId);
        if (Objects.isNull(bank)) {
            return FsResponseGen.failMsg("银行卡不存在");
        }
        if (!userId.equals(bank.getUserId())) {
            return FsResponseGen.failMsg("银行卡错误");
        }

        if (money.compareTo(new BigDecimal("5")) < 0) {
            return FsResponseGen.failMsg("单笔最低提现5元");
        }
        if (money.compareTo(new BigDecimal("5000")) > 0) {
            return FsResponseGen.failMsg("单笔最高提现5000元");
        }

        BigDecimal income = balanceService.selectByUserId(userId).getIncomeBalance();

        //余额不足
        if (income.compareTo(money) < 0) {
            return FsResponseGen.successData(YiChatMsgCode.WITHDRAW_APPLY_BALANCE_LITTLE, null);
        }

        WithdrawConfigDto config = getUserWithdrawConfig();
        // 今日提现次数
        Example example = new Example(UserWithdraw.class);
        Date date = new Date();
        example.createCriteria().andEqualTo("userId", userId).andBetween("ctime", DateUtils.formatDate(date, "yyyy-MM-dd 00:00:00"), DateUtils.formatDate(date, "yyyy-MM-dd 23:59:59"));
        int count = userWithdrawMapper.selectCountByExample(example);

        String setCount=config.getCount();
        int setCountInt=3;
        try {
            setCountInt=Integer.parseInt(setCount);
        }catch (Exception e){
            e.printStackTrace();
        }
        if (count > setCountInt-1) {
            return FsResponseGen.failMsg("单日最多提现"+setCount+"次");
        }

        String xsBalance = redisService.getVal("xs_balance");
        String hjBalance = redisService.getVal("hj_balance");
        if (xsBalance != null && hjBalance != null) {
            BigDecimal xsBalanceBig = new BigDecimal(xsBalance);
            BigDecimal hjBalanceBig = new BigDecimal(hjBalance);
            if (hjBalanceBig.compareTo(money) < 0 && xsBalanceBig.compareTo(money) > 0) {
                return FsResponseGen.failMsg("该渠道今日已受限，请切换至渠道二提现");
            } else {
                redisService.setVal("hj_balance", hjBalanceBig.subtract(money).toString());
            }
        }


        //计算手续费
        BigDecimal rateF = new BigDecimal(config.getRate());
        rateF = money.multiply(rateF);
        rateF = rateF.divide(new BigDecimal("100"));
        rateF=rateF.add(new BigDecimal(config.getAdd()));
        // rateF = rateF.add(new BigDecimal("1"));
        rateF = rateF.setScale(2, BigDecimal.ROUND_HALF_UP);

        //计算实际到账
        BigDecimal realMoney = money.subtract(rateF).setScale(2, BigDecimal.ROUND_HALF_UP);

        //因为最低提现5元，所以实际到账不会低于0元


        //生成提现申请
        UserWithdraw withdraw = new UserWithdraw();
        withdraw.setBankName(bank.getBankName());
        withdraw.setBankNumber(bank.getBankNumber());
        withdraw.setMemo(memo);
        withdraw.setFutureMoney(realMoney);
        withdraw.setMoney(money);
        withdraw.setDetail("本次提现 " + money + " 元，手续费：" + rateF + " 元，实际到账：" + realMoney + "元");
        withdraw.setType(1);
        withdraw.setUserId(userId);
        withdraw.setCtime(new Date());
        withdraw.setStatus(0);
        userWithdrawMapper.insertUseGeneratedKeys(withdraw);

        //扣除余额到冻结
        balanceService.update(userId, BalanceType.WITHDRAW_APPLY, money, Long.valueOf(withdraw.getId()), "提现申请");

        return FsResponseGen.successData(DtoChangeUtils.getDto(NumberUtils.halfTwo(income.subtract(money)), v -> {
            UserWidthdrawDto dto = new UserWidthdrawDto();
            dto.setBalance(v);
            return dto;
        }));
    }



//    @Override
//    public void autoChekWithdaw() {
//        SysDict auto = sysDictService.selectOne(DictKey.sys_withdraw_auto);
//        logger.debug("提现审核检查");
//
//        if (Objects.nonNull(auto)) {
//            //自动通过
//            String limitMoney = Optional.ofNullable(sysDictService.selectOne(DictKey.sys_withdraw_auto_money)).map(SysDict::getValue).orElse("0");
//            String maxSecondStr = Optional.ofNullable(sysDictService.selectOne(DictKey.sys_withdraw_auto_time)).map(SysDict::getValue).orElse("120");
//
//            logger.debug("自动提现金额：{}、时长：{}", limitMoney, maxSecondStr);
//            int maxSecond;
//            try {
//                maxSecond = Integer.parseInt(maxSecondStr);
//            } catch (Exception e) {
//                maxSecond = 120;
//            }
//            Example example = new Example(UserWithdraw.class);
//            example.createCriteria().andEqualTo("status", 0).andLessThanOrEqualTo("money", limitMoney);
//            example.setOrderByClause("  id asc");
//            List<UserWithdraw> withdraws = userWithdrawMapper.selectByExample(example);
//
//            logger.debug("此次自动提现数：{}", limitMoney, maxSecondStr);
//            Random random = new Random();
//            for (UserWithdraw withdraw : withdraws) {
//                int second = random.nextInt(maxSecond);
//                try {
//                    TimeUnit.SECONDS.sleep(second);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
//                Example example2 = new Example(UserWithdraw.class);
//                example2.createCriteria().andEqualTo("status", 1).andEqualTo("userId", withdraw.getUserId());
//                int count = userWithdrawMapper.selectCountByExample(example2);
//                if (count > 0) {
//                    logger.debug("自动提现：{}", withdraw.getId());
//                    balanceService.checkWithdraw(withdraw.getId(), 1, null);
//                }
//            }
//        }
//    }

    @Override
    public FsResponse selectList(FsPage page, Long userId) {
        Example example = new Example(UserWithdraw.class);
        example.createCriteria().andEqualTo("userId", userId);
        example.setOrderByClause(" ctime desc");
        PageHelper.startPage(page.getPageNo(), page.getPageSize());
        return DtoChangeUtils.getPageList(userWithdrawMapper.selectByExample(example), v -> {
            UserWithdrawDto dto = new UserWithdrawDto();
             dto.setMoney(v.getMoney());
            dto.setRefuseReason(v.getRefuseReason());
            dto.setStatus(v.getStatus());
            if (v.getStatus() == 0) {
                dto.setTime(DateUtils.formatDate(v.getCtime()));
            } else {
                dto.setTime(DateUtils.formatDate(v.getCheckTime()));
            }
            dto.setBankNumber(v.getBankNumber());
            return dto;
        });
    }

    private Integer countExistApply(Long userId) {
        Example example = new Example(UserWithdraw.class);
        example.createCriteria().andEqualTo("userId", userId).andEqualTo("status", 0);
        return userWithdrawMapper.selectCountByExample(example);
    }
}
